//this file is part of eMule
//Copyright (C)2002 Merkur ( merkur-@users.sourceforge.net / http://www.emule-project.net )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.


// ServerListCtrl.cpp : implementation file
//

//#include "stdafx.h"
#include "emule.h"
#include "ServerListCtrl.h"
#include "muuli_wdr.h"

// CServerListCtrl

#define SYSCOLOR(x) (wxSystemSettings::GetColour(x))

#include <wx/event.h>
BEGIN_EVENT_TABLE(CServerListCtrl,CMuleListCtrl)
  EVT_LIST_ITEM_RIGHT_CLICK(ID_SERVERLIST,CServerListCtrl::OnRclickServlist)
  EVT_LIST_COL_CLICK(ID_SERVERLIST,CServerListCtrl::OnLvnColumnclickServlist)
  EVT_LEFT_DCLICK(CServerListCtrl::OnLDclick)
END_EVENT_TABLE()

  // implemented by processevent():
  //  EVT_MENU(MP_CONNECTTO,CServerListCtrl::OnConnectTo)
  //EVT_MENU(MP_REMOVE,CServerListCtrl::OnRemove)
  //EVT_MENU(MP_GETED2KLINK,CServerListCtrl::OnCopyLink)

//IMPLEMENT_DYNAMIC(CServerListCtrl, CMuleListCtrl/*CTreeCtrl*/)
CServerListCtrl::CServerListCtrl(){
  memset(&asc_sort,0,8);
}

CServerListCtrl::CServerListCtrl(wxWindow*& parent,int id,const wxPoint& pos,wxSize siz,int flags)
  : CMuleListCtrl(parent,id,pos,siz,flags)
{
  memset(&asc_sort,0,8);
  m_ServerPrioMenu=NULL;
  m_ServerMenu=NULL;
}

void CServerListCtrl::OnLDclick(wxMouseEvent& event)
{
  int lips=0;
  int index=HitTest(event.GetPosition(),lips);
  if(index>=0) SetItemState(index,wxLIST_STATE_SELECTED,wxLIST_STATE_SELECTED);
  wxCommandEvent nulEvt;
  OnConnectTo(nulEvt);
}

void CServerListCtrl::OnRclickServlist(wxListEvent& event)
{
    // Check if clicked item is selected. If not, unselect all and select it.
  long item=-1;
  if (!GetItemState(event.GetIndex(), wxLIST_STATE_SELECTED)) {
    for (;;) {
      item = GetNextItem(item,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
      if (item==-1) break;
      SetItemState(item, 0, wxLIST_STATE_SELECTED);
    }
    SetItemState(event.GetIndex(), wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
  }
 
  // Create up-to-date popupmenu
  if(m_ServerMenu==NULL) {
    m_ServerMenu=new wxMenu(_("Server"));
    m_ServerPrioMenu=new wxMenu();
    m_ServerPrioMenu->Append(MP_PRIOLOW,_("Low"));
    m_ServerPrioMenu->Append(MP_PRIONORMAL,_("Normal"));
    m_ServerPrioMenu->Append(MP_PRIOHIGH,_("High"));

    m_ServerMenu->Append(MP_CONNECTTO,_("Connect to this server"));
    m_ServerMenu->Append(999999,_("Priority"),m_ServerPrioMenu);
    m_ServerMenu->Append(MP_ADDTOSTATIC,_("Add to static"));
    m_ServerMenu->Append(MP_REMOVEFROMSTATIC, GetResString(IDS_REMOVEFROMSTATIC));
    m_ServerMenu->Enable(MP_ADDTOSTATIC,FALSE);
    m_ServerMenu->Enable(MP_REMOVEFROMSTATIC,FALSE);
    m_ServerMenu->AppendSeparator();
    m_ServerMenu->Append(MP_REMOVE,_("Remove server"));
    m_ServerMenu->Append(MP_REMOVEALL,_("Remove all servers"));
    m_ServerMenu->AppendSeparator();
    m_ServerMenu->Append(MP_GETED2KLINK,_("Copy ED2k &link to clipboard"));
  }

  // set states
  CServer* test=NULL;
  int selidx;
  selidx=GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
  if(selidx!=-1) {
    m_ServerMenu->Enable(999999,TRUE);
  } else {
    m_ServerMenu->Enable(999999,FALSE);
  }
  if(selidx!=-1){
    test=(CServer*)GetItemData(selidx);
    if(test) {
      if(test->IsStaticMember()) {
	m_ServerMenu->Enable(MP_REMOVEFROMSTATIC,TRUE);
	m_ServerMenu->Enable(MP_ADDTOSTATIC,FALSE);
      } else {
	m_ServerMenu->Enable(MP_REMOVEFROMSTATIC,FALSE);
	m_ServerMenu->Enable(MP_ADDTOSTATIC,TRUE);
      }
    } else {
      m_ServerMenu->Enable(MP_REMOVEFROMSTATIC,FALSE);
      m_ServerMenu->Enable(MP_ADDTOSTATIC,FALSE);
    }
  } else {
    m_ServerMenu->Enable(MP_REMOVEFROMSTATIC,FALSE);
    m_ServerMenu->Enable(MP_ADDTOSTATIC,FALSE);
  }
  
  PopupMenu(m_ServerMenu,event.GetPoint());
}

void CServerListCtrl::OnConnectTo(wxCommandEvent& event)
{
  int connectcounter=0;
  long item=-1;

  if ( this->GetSelectedItemCount()>1 ) {
    theApp.serverconnect->Disconnect();
    
    item=-1;
    do {
      item=GetNextItem(item,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
      if(item>-1) {
	connectcounter++;
	theApp.serverconnect->ConnectToServer((CServer*)this->GetItemData(item),true);
      }
    } while(item!=-1 && connectcounter<10);
  } else {
    item=GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
    if(item>-1) {
      theApp.serverconnect->ConnectToServer((CServer*)GetItemData(item));
    }
  }

  theApp.emuledlg->ShowConnectionState(false);  
}

void CServerListCtrl::OnRemove(wxEvent& event)
{
  long item=-1;
  
  if ( this->GetSelectedItemCount()>1 ) {
    item=-1;
    do {
      item=GetNextItem(item,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
      if(item>-1) {
	theApp.emuledlg->serverwnd->serverlistctrl->RemoveServer((CServer*)this->GetItemData(item));
      }
    } while(item!=-1);
  } else {
    item=GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
    if(item>-1) {
      theApp.emuledlg->serverwnd->serverlistctrl->RemoveServer((CServer*)this->GetItemData(item));
    }
  }
}


void CServerListCtrl::OnCopyLink(wxCommandEvent& event)
{
  long item=-1;
  wxString buffer,link;

  while( (item=GetNextItem(item,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED)) != -1 )
    {
      CServer* change = (CServer*) this->GetItemData(item);
      buffer=buffer.Format("ed2k:|server|%s|%d|", change->GetFullIP(), change->GetPort());
      if(link.Length()>0)
	buffer="\n"+buffer;
      link += buffer; 
    }
  theApp.CopyTextToClipboard(link); 
}

void CServerListCtrl::InitSort()
{
	LoadSettings(CPreferences::tableServer);

	// Barry - Use preferred sort order from preferences
	int sortItem = theApp.glob_prefs->GetColumnSortItem(CPreferences::tableServer);
	bool sortAscending = theApp.glob_prefs->GetColumnSortAscending(CPreferences::tableServer);
	SetSortArrow(sortItem, sortAscending);
	SortItems(SortProc, sortItem + (sortAscending ? 0:100));
	ShowFilesCount();
}

bool CServerListCtrl::Init(CServerList* in_list){ 
  printf("Serverlist inited. to %x\n",in_list);
  server_list = in_list;

  InsertColumn(0,_("Server Name"),wxLIST_FORMAT_LEFT,150);
  InsertColumn(1,_("IP"),wxLIST_FORMAT_LEFT,140);
  InsertColumn(2,_("Description") ,wxLIST_FORMAT_LEFT, 150);
  InsertColumn(3,_("Ping"),wxLIST_FORMAT_LEFT, 50);
  InsertColumn(4,_("Users"),wxLIST_FORMAT_LEFT, 50);
  InsertColumn(5,_("Files"),wxLIST_FORMAT_LEFT, 50);
  InsertColumn(6,_("Preference"),wxLIST_FORMAT_LEFT, 60);
  InsertColumn(7,_("Failed"),wxLIST_FORMAT_LEFT, 50);
  InsertColumn(8,_("Static"),wxLIST_FORMAT_LEFT, 50);

  asc_sort[3]=true;asc_sort[4]=true;asc_sort[5]=true;asc_sort[7]=true;
  // perhaps not yet
  //LoadSettings(CPreferences::tableServer);

#if 0
	this->ModifyStyle(0,TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS);
	// Set Imagelist
	server_list = in_list;
	imagelist.Create(16,16,ILC_COLOR|ILC_MASK,0,10);
	imagelist.SetBkColor(RGB(255,255,255));
	imagelist.Add(theApp.LoadIcon(IDI_ICON1));

	this->SetImageList(&imagelist,LVSIL_SMALL);//TVSIL_NORMAL);
	this->ModifyStyle(LVS_SINGLESEL|LVS_LIST|LVS_ICON|LVS_SMALLICON,LVS_REPORT); //here the CListCtrl is set to report-style

	InsertColumn(0,GetResString(IDS_SL_SERVERNAME),LVCFMT_LEFT, 150);
	InsertColumn(1,GetResString(IDS_IP),LVCFMT_LEFT, 140);
	InsertColumn(2,GetResString(IDS_DESCRIPTION) ,LVCFMT_LEFT, 150);
	InsertColumn(3,GetResString(IDS_PING),LVCFMT_LEFT, 50);
	InsertColumn(4,GetResString(IDS_UUSERS),LVCFMT_LEFT, 50);
	InsertColumn(5,GetResString(IDS_PW_FILES) ,LVCFMT_LEFT, 50);
	InsertColumn(6,GetResString(IDS_PREFERENCE),LVCFMT_LEFT, 60);
	InsertColumn(7,GetResString(IDS_UFAILED),LVCFMT_LEFT, 50);
	InsertColumn(8,GetResString(IDS_STATICSERVER),LVCFMT_LEFT, 50);

	asc_sort[3]=true;asc_sort[4]=true;asc_sort[5]=true;asc_sort[7]=true;

	LoadSettings(CPreferences::tableServer);
#endif
	return true;
} 

CServerListCtrl::~CServerListCtrl() {
}

void CServerListCtrl::Localize() {
#if 0
	CHeaderCtrl* pHeaderCtrl = GetHeaderCtrl();
	HDITEM hdi;
	hdi.mask = HDI_TEXT;
	CString strRes;

	strRes = GetResString(IDS_SL_SERVERNAME);
	hdi.pszText = strRes.GetBuffer();
	pHeaderCtrl->SetItem(0, &hdi);
	strRes.ReleaseBuffer();

	strRes = GetResString(IDS_IP);
	hdi.pszText = strRes.GetBuffer();
	pHeaderCtrl->SetItem(1, &hdi);
	strRes.ReleaseBuffer();

	strRes = GetResString(IDS_DESCRIPTION);
	hdi.pszText = strRes.GetBuffer();
	pHeaderCtrl->SetItem(2, &hdi);
	strRes.ReleaseBuffer();

	strRes = GetResString(IDS_PING);
	hdi.pszText = strRes.GetBuffer();
	pHeaderCtrl->SetItem(3, &hdi);
	strRes.ReleaseBuffer();

	strRes = GetResString(IDS_UUSERS);
	hdi.pszText = strRes.GetBuffer();
	pHeaderCtrl->SetItem(4, &hdi);
	strRes.ReleaseBuffer();

	strRes = GetResString(IDS_PW_FILES);
	hdi.pszText = strRes.GetBuffer();
	pHeaderCtrl->SetItem(5, &hdi);
	strRes.ReleaseBuffer();

	strRes = GetResString(IDS_PREFERENCE);
	hdi.pszText = strRes.GetBuffer();
	pHeaderCtrl->SetItem(6, &hdi);
	strRes.ReleaseBuffer();

	strRes = GetResString(IDS_UFAILED);
	hdi.pszText = strRes.GetBuffer();
	pHeaderCtrl->SetItem(7, &hdi);
	strRes.ReleaseBuffer();

	strRes = GetResString(IDS_STATICSERVER);
	hdi.pszText = strRes.GetBuffer();
	pHeaderCtrl->SetItem(8, &hdi);
	strRes.ReleaseBuffer();
#endif
}

/*void CServerListCtrl::ShowServers(){ 
   DeleteAllItems(); 
   int i=0; 
   CString temp; 
   for(POSITION pos = server_list->list.GetHeadPosition(); pos != NULL;server_list->list.GetNext(pos)) { 
      CServer* cur_server = server_list->list.GetAt(pos); 
      InsertItem(LVIF_TEXT|LVIF_PARAM,i,cur_server->GetListName(),0,0,0,(LPARAM)cur_server);
	  RefreshServer( cur_server );
      i++; 
   } 
}
*/

void CServerListCtrl::RemoveServer(CServer* todel,bool bDelToList){
  //LVFINDINFO find;
  //find.flags = LVFI_PARAM;
  //find.lParam = (LPARAM)todel;
  sint32 result = FindItem(-1,(long)todel);
  if (result != (-1) ){
    server_list->RemoveServer((CServer*)GetItemData(result));
    DeleteItem(result); 
  }
  return;
}

// Remove Dead Servers
void CServerListCtrl::RemoveDeadServer(){
	if( theApp.glob_prefs->DeadServer() ){
	  //ShowWindow(SW_HIDE); 
		for(POSITION pos = server_list->list.GetHeadPosition(); pos != NULL;server_list->list.GetNext(pos)) { 
			CServer* cur_server = server_list->list.GetAt(pos); 
			if( cur_server->GetFailedCount() > theApp.glob_prefs->GetDeadserverRetries() ){	// MAX_SERVERFAILCOUNT 
				RemoveServer(cur_server);
				pos = server_list->list.GetHeadPosition();
			}
		}
		//ShowWindow(SW_SHOW); 
	}
}

bool CServerListCtrl::AddServer(CServer* toadd,bool bAddToList){ 
   if (!server_list->AddServer(toadd)) 
      return false; 
   if (bAddToList) 
   {
     uint32 itemnr=GetItemCount();
     uint32 newid=InsertItem(itemnr,toadd->GetListName());
     SetItemData(newid,(long)toadd);
     wxListItem myitem;
     myitem.m_itemId=newid;
     myitem.SetBackgroundColour(SYSCOLOR(wxSYS_COLOUR_LISTBOX));
     SetItem(myitem);
     RefreshServer(toadd);
     //uint32 itemnr = GetItemCount();
     //InsertItem(LVIF_TEXT|LVIF_PARAM,itemnr,toadd->GetListName(),0,0,1,(LPARAM)toadd);
     //RefreshServer( toadd );
   } 
   ShowFilesCount();
   return true; 
}


void CServerListCtrl::RefreshServer( CServer* server ){
  long itemnr=FindItem(-1,(long)server);
  if(itemnr==(-1))
    return;

  wxString temp;
  if( !server )
    return;
  temp=wxString::Format( "%s : %i",server->GetAddress(),server->GetPort());
  SetItem(itemnr,1,temp);
  if(server->GetListName()){
    temp=wxString::Format( server->GetListName());
    SetItem(itemnr,0,temp);
  }
  if(server->GetDescription()){
    temp=wxString::Format( server->GetDescription());
    SetItem(itemnr,2,temp);
  }
  if(1) { //server->GetPing()){
    if(server->GetPing())
      temp=wxString::Format( "%i",server->GetPing()); 
    else temp="";
    SetItem(itemnr,3,temp);
  } else {
    printf("%lx: ei ping\n",server);
    SetItem(itemnr,3,"Ei ei");
  }
  if(server->GetUsers()){
    temp=wxString::Format( "%i",server->GetUsers()); 
    SetItem(itemnr,4,temp);
  }
  if(server->GetFiles()){
    temp=wxString::Format( "%i",server->GetFiles()); 
    SetItem(itemnr,5,temp);
  }
  if(server->GetPreferences()){
    temp=wxString::Format( "%i",server->GetPreferences()); 
    SetItem(itemnr,6,temp);
  }
  switch(server->GetPreferences()){
  case SRV_PR_LOW:
    temp.Printf( GetResString(IDS_PRIOLOW));
    SetItem(itemnr,6,temp);
    break;
  case SRV_PR_NORMAL:
    temp.Printf( GetResString(IDS_PRIONORMAL));
    SetItem(itemnr,6,temp);
    break;
  case SRV_PR_HIGH:
    temp.Printf( GetResString(IDS_PRIOHIGH));
    SetItem(itemnr,6,temp);
    break;
  default:
    temp.Format( GetResString(IDS_PRIONOPREF));
    SetItem(itemnr,6,temp);
  }
  if( server->GetFailedCount() < 0 )
    server->ResetFailedCount();
  temp=wxString::Format( "%i",server->GetFailedCount()); 
  SetItem(itemnr,7,temp);
  
  if (server->IsStaticMember()) SetItem(itemnr,8,_("Yes")); //GetResString(IDS_YES)); 
  else SetItem(itemnr,8,_("No")); //GetResString(IDS_NO));
}

#if 0
BEGIN_MESSAGE_MAP(CServerListCtrl, CMuleListCtrl/*CTreeCtrl*/) 
   ON_NOTIFY_REFLECT(NM_RCLICK, OnNMRclickServlist) 
   ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnLvnColumnclickServlist) 
   ON_NOTIFY_REFLECT (NM_DBLCLK, OnNMLdblclk) //<-- mod bb 27.09.02 
END_MESSAGE_MAP()

// CServerListCtrl message handlers

void CServerListCtrl::OnNMRclickServlist(NMHDR *pNMHDR, LRESULT *pResult) 
{ 
   POINT point; 
   ::GetCursorPos(&point); 

   // tecxx 0609 2002 
   // fix - on right click, we also want to change the current selection like the left click does 
   CPoint p = point; 
   ScreenToClient(&p); 
   int it = HitTest(p); 
   if (it != -1) 
      SetSelectionMark(it);   // display selection mark correctly! 
   // fix end 

   // Create up-to-date popupmenu
   UINT flags;
   CTitleMenu m_ServerMenu;
   CMenu m_ServerPrioMenu;
   // set state of selection-dependent menuitems
   flags=MF_STRING || MF_DISABLED;
   if (this->GetSelectionMark() != -1) if (((CServer*)GetItemData(GetSelectionMark())) != NULL) flags=MF_STRING;
   
   // add priority switcher
   m_ServerPrioMenu.CreateMenu();
   m_ServerPrioMenu.AppendMenu(MF_STRING,MP_PRIOLOW,GetResString(IDS_PRIOLOW));
   m_ServerPrioMenu.AppendMenu(MF_STRING,MP_PRIONORMAL,GetResString(IDS_PRIONORMAL));
   m_ServerPrioMenu.AppendMenu(MF_STRING,MP_PRIOHIGH,GetResString(IDS_PRIOHIGH));

   m_ServerMenu.CreatePopupMenu(); 
   m_ServerMenu.AddMenuTitle(GetResString(IDS_EM_SERVER));
   m_ServerMenu.AppendMenu(flags,MP_CONNECTTO, GetResString(IDS_CONNECTTHIS)); 
   m_ServerMenu.AppendMenu(flags|MF_POPUP,(UINT_PTR)m_ServerPrioMenu.m_hMenu, GetResString(IDS_PRIORITY));
   m_ServerMenu.AppendMenu(flags,MP_ADDTOSTATIC, GetResString(IDS_ADDTOSTATIC));
   m_ServerMenu.AppendMenu(MF_STRING|MF_SEPARATOR);	
   m_ServerMenu.AppendMenu(flags,MP_REMOVE,   GetResString(IDS_REMOVETHIS)); 
   m_ServerMenu.AppendMenu(MF_STRING,MP_REMOVEALL, GetResString(IDS_REMOVEALL));
   m_ServerMenu.AppendMenu(MF_SEPARATOR); 
   m_ServerMenu.AppendMenu(MF_STRING,MP_GETED2KLINK, GetResString(IDS_DL_LINK1) );

   m_ServerMenu.SetDefaultItem(MP_CONNECTTO);
   m_ServerMenu.TrackPopupMenu(TPM_LEFTALIGN |TPM_RIGHTBUTTON, point.x, point.y, this); 

   m_ServerMenu.DestroyMenu();

   *pResult = 0; 
}
#endif

bool CServerListCtrl::ProcessEvent(wxEvent& evt) {
  if(evt.GetEventType()!=wxEVT_COMMAND_MENU_SELECTED)
    return CMuleListCtrl::ProcessEvent(evt);
  
  wxCommandEvent& event=(wxCommandEvent&)evt;
  
  //int item= this->GetSelectionMark(); 
  int item=GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
  if (event.GetId()==MP_REMOVEALL)
    { 
      if( theApp.serverconnect->IsConnecting() ){
	theApp.downloadqueue->StopUDPRequests(); 
	theApp.serverconnect->StopConnectionTry();
	theApp.serverconnect->Disconnect();
	theApp.emuledlg->ShowConnectionState(false);
      }
      //ShowWindow(SW_HIDE); 
      server_list->RemoveAllServers(); 
      DeleteAllItems(); 
      //ShowWindow(SW_SHOW);
      ShowFilesCount();
      return true;
    } 
  
  if (item != -1){ 
    if (((CServer*)GetItemData(item)) != NULL){ 
      
      switch (event.GetId()){ 
      case MP_CONNECTTO: 
	{
	  if ( this->GetSelectedItemCount()>1 ) {
	    CServer* aServer;
	    uint32   newPosition=0;
	    
	    theApp.serverconnect->Disconnect();
	    int pos=GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
	    while (pos!=-1 )
	      { 
		item = pos; //this->GetNextSelectedItem(pos); 
		if (item>-1) {
		  aServer=(CServer*)this->GetItemData(item);
		  theApp.serverlist->MoveServerDown(aServer);
		}
		pos=GetNextItem(pos,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
	      }
	    theApp.serverconnect->ConnectToAnyServer( theApp.serverlist->GetServerCount()-  this->GetSelectedItemCount(),false, false );
	  } else {
	    theApp.serverconnect->ConnectToServer((CServer*)GetItemData(item));
	  }
	  theApp.emuledlg->ShowConnectionState(false);
	  break; 
	}			
      case MP_REMOVE: 
	{ 
	  //POSITION pos;
	  int pos=GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
	  while (pos!=-1) //GetFirstSelectedItemPosition()!=NULL) //(pos != NULL) 
	    { 
	      //pos=GetFirstSelectedItemPosition();
	      item = pos; //this->GetNextSelectedItem(pos); 
	      server_list->RemoveServer( (CServer*)this->GetItemData(item));
	      DeleteItem(item);
	      pos=GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
	    }
	  ShowFilesCount();
	  //ShowWindow(SW_SHOW); 
	  break; 
	}
      case MP_ADDTOSTATIC:{
	//POSITION pos=GetFirstSelectedItemPosition();
	int pos=GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
	while( pos != -1 ){
	  CServer* change = (CServer*)this->GetItemData(pos);
	  if (!StaticServerFileAppend(change))
	    return false;
	  change->SetIsStaticMember(true);
	  theApp.emuledlg->serverwnd->serverlistctrl->RefreshServer(change);
	  pos=GetNextItem(pos,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
	}
	break;
      }
			// Remove Static Servers [Barry]
      case MP_REMOVEFROMSTATIC:
	{
	  //POSITION pos=GetFirstSelectedItemPosition();
	  int pos=GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
	  while( pos != -1 ){
	    CServer* change = (CServer*)this->GetItemData(pos);
	    if (!StaticServerFileRemove(change))
	      return false;
	    change->SetIsStaticMember(false);
	    theApp.emuledlg->serverwnd->serverlistctrl->RefreshServer(change);
	    pos=GetNextItem(pos,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
	  }
	  break;
	}
      case MP_PRIOLOW:
	{
	  //POSITION pos = this->GetFirstSelectedItemPosition();
	  int pos=GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
	  while( pos != -1 ){
	    CServer* change = (CServer*)this->GetItemData(pos);
	    change->SetPreference( SRV_PR_LOW);
	    //					if (change->IsStaticMember())
	    //						StaticServerFileAppend(change); //Why are you adding to static when changing prioity? If I want it static I set it static.. I set server to LOW because I HATE this server, not because I like it!!!
	    theApp.emuledlg->serverwnd->serverlistctrl->RefreshServer(change);
	    //POSITION pos = this->GetFirstSelectedItemPosition();
	    pos=GetNextItem(pos,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
	  }
	  break;
	}
      case MP_PRIONORMAL:
	{
	  //POSITION pos = this->GetFirstSelectedItemPosition();
	  int pos=GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
	  while( pos != -1 ){
	    CServer* change = (CServer*)this->GetItemData(pos);
	    change->SetPreference( SRV_PR_NORMAL );
	    //					if (change->IsStaticMember())
	    //						StaticServerFileAppend(change);
	    theApp.emuledlg->serverwnd->serverlistctrl->RefreshServer(change);
	    //POSITION pos = this->GetFirstSelectedItemPosition();
	    pos=GetNextItem(pos,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
	  }
	  break;
	}
      case MP_PRIOHIGH:
	{
	  //POSITION pos = this->GetFirstSelectedItemPosition();
	  int pos=GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
	  while( pos != -1 ){
	    CServer* change = (CServer*)this->GetItemData(pos);
	    change->SetPreference( SRV_PR_HIGH );
	    //					if (change->IsStaticMember())
	    //						StaticServerFileAppend(change);
	    theApp.emuledlg->serverwnd->serverlistctrl->RefreshServer(change);
	    //POSITION pos = this->GetFirstSelectedItemPosition();
	    pos=GetNextItem(pos,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
	  }
	  break;
	}
      case MP_GETED2KLINK: 
	{ 
	  //POSITION pos = this->GetFirstSelectedItemPosition(); 
	  int pos=GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
	  wxString buffer, link; 
	  while( pos != -1 ){ 
	    CServer* change = (CServer*)this->GetItemData(pos);
	    buffer.Printf("ed2k://|server|%s|%d|/", change->GetFullIP(), change->GetPort()); 
	    if (link.Length()>0) buffer="\n"+buffer;
	    link += buffer; 
	    //POSITION pos = this->GetFirstSelectedItemPosition(); 
	    pos=GetNextItem(pos,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
	  } 
	  theApp.CopyTextToClipboard(link); 
	  break; 
	}
#if 0
      case Irc_SetSendLink:
	{
	  POSITION pos = this->GetFirstSelectedItemPosition(); 
	  CString buffer, link; 
	  while( pos != NULL ){ 
	    CServer* change = (CServer*)this->GetItemData(this->GetNextSelectedItem(pos)); 
	    buffer.Format("ed2k://|server|%s|%d|/", change->GetFullIP(), change->GetPort()); 
	    if (link.GetLength()>0) buffer="\n"+buffer;
	    link += buffer; 
	    POSITION pos = this->GetFirstSelectedItemPosition(); 
	  } 
	  theApp.emuledlg->ircwnd.SetSendFileString(link);
	  break;
	}
#endif	
      } 
    } 
  } 
  return CMuleListCtrl::ProcessEvent(evt); 
}
#if 0
void CServerListCtrl::OnNMLdblclk(NMHDR *pNMHDR, LRESULT *pResult){ // mod bb 27.09.02
	if (GetSelectionMark() != (-1)) {
		theApp.serverconnect->ConnectToServer((CServer*)GetItemData(GetSelectionMark())); 
	   theApp.emuledlg->ShowConnectionState(false);
	}
}

bool CServerListCtrl::AddServermetToList(CString strFile) 
{ 
   bool flag=server_list->AddServermetToList(strFile);
   RemoveDeadServer();
   return flag;
}
#endif

bool CServerListCtrl::AddServermetToList(wxString strFile) 
{ 
  Freeze();
  bool flag=server_list->AddServermetToList(CString(strFile.GetData()));
  RemoveDeadServer();
  ShowFilesCount();
  Thaw();
  return flag;
}

void CServerListCtrl::OnLvnColumnclickServlist(wxListEvent& evt) //NMHDR *pNMHDR, LRESULT *pResult) 
{ 
  // Barry - Store sort order in preferences
  // Determine ascending based on whether already sorted on this column
  int sortItem = theApp.glob_prefs->GetColumnSortItem(CPreferences::tableServer);
  bool m_oldSortAscending = theApp.glob_prefs->GetColumnSortAscending(CPreferences::tableServer);
  bool sortAscending = (sortItem != evt.GetColumn()) ? true : !m_oldSortAscending;
  
  // Item is column clicked
  sortItem = evt.GetColumn();
  
  // Save new preferences
  theApp.glob_prefs->SetColumnSortItem(CPreferences::tableServer, sortItem);
  theApp.glob_prefs->SetColumnSortAscending(CPreferences::tableServer, sortAscending);
  
  // Sort table
  SetSortArrow(sortItem, sortAscending);
  SortItems(SortProc, sortItem + (sortAscending ? 0:100));
} 

int CServerListCtrl::SortProc(long lParam1, long lParam2, long lParamSort){ 
   CServer* item1 = (CServer*)lParam1; 
   CServer* item2 = (CServer*)lParam2; 
   if((item1 == NULL) || (item2 == NULL)) return 0; 
   int iTemp=0; 
   int counter1; 
   int counter2; 
    
   switch(lParamSort){ 
      case 0: //(List) Server-name asc
		  return CString(item1->GetListName()).CmpNoCase(item2->GetListName());
      case 100: //(List) Server-name desc 
		  return CString(item2->GetListName()).CmpNoCase(item1->GetListName());
      case 1:{ //IP asc
		  if( item1->HasDynIP() && item2->HasDynIP() )
			  return CString(item1->GetDynIP()).CmpNoCase(item2->GetDynIP());
		  else if( item1->HasDynIP() )
			  return 1;
		  else if( item2->HasDynIP() )
			  return 0;
		  else{
			  CString sIP1, sIP2, sTemp1, sTemp2; 
			  counter1 = counter2 = iTemp = 0; 
			  sIP1 = item2->GetFullIP(); 
			  sIP2 = item1->GetFullIP(); 
			  int a[4],b[4];
			  sscanf(sIP1.GetData(),"%d.%d.%d.%d",&a[0],&a[1],&a[2],&a[3]);
			  sscanf(sIP2.GetData(),"%d.%d.%d.%d",&b[0],&b[1],&b[2],&b[3]);
			  for(int i=0;iTemp==0;i++) {
			    iTemp=b[i]-a[i];
			    if(i>3) {
			      return item1->GetPort()-item2->GetPort();
			    }
			  }
			  
#if 0
			  for(int i=0; iTemp == 0 ; i++){ 
				  sTemp1 = sIP1.Tokenize(".",counter1); 
				  sTemp2 = sIP2.Tokenize(".",counter2); 
				  iTemp = atoi(sTemp2) - atoi(sTemp1); 
				  if(i>2){ 
					  return item1->GetPort() - item2->GetPort(); 
				  } 
			  } 
#endif
			  return iTemp; 
		  }
			 }
      case 101:{ //IP desc 
		  if( item1->HasDynIP() && item2->HasDynIP() )
			  return CString(item2->GetDynIP()).CmpNoCase(item1->GetDynIP());
		  else if( item1->HasDynIP() )
			  return 0;
		  else if( item2->HasDynIP() )
			  return 1;
		  else{
			  CString s2IP1, s2IP2, s2Temp1, s2Temp2; 
			  counter1 = counter2 = iTemp = 0; 
			  s2IP1 = item2->GetFullIP(); 
			  s2IP2 = item1->GetFullIP(); 

			  int a[4],b[4];
			  sscanf(s2IP1.GetData(),"%d.%d.%d.%d",&a[0],&a[1],&a[2],&a[3]);
			  sscanf(s2IP2.GetData(),"%d.%d.%d.%d",&b[0],&b[1],&b[2],&b[3]);
			  for(int i=0;iTemp==0;i++) {
			    iTemp=a[i]-b[i];
			    if(i>3) {
			      return item2->GetPort()-item1->GetPort();
			    }
			  }
#if 0
			  for(int i=0; iTemp == 0 ; i++){ 
				  s2Temp1 = s2IP1.Tokenize(".",counter1);
				  s2Temp2 = s2IP2.Tokenize(".",counter2); 
				  iTemp = atoi(s2Temp1) - atoi(s2Temp2); 
				  if(i>2){
					  return item2->GetPort() - item1->GetPort(); 
				  } 
			  }
#endif
			  return iTemp; 
		  }
			  }
      case 2: //Description asc 
         if((item1->GetDescription() != NULL) && (item2->GetDescription() != NULL)) 
            //the 'if' is necessary, because the Description-String is not 
            //always initialisized in server.cpp 
			return CString(item2->GetDescription()).CmpNoCase(item1->GetDescription());
		 else if( item1->GetDescription() == NULL )
			 return 1;
		 else
			 return 0;
      case 102: //Desciption desc 
         if((item1->GetDescription() != NULL) && (item2->GetDescription() != NULL))
			return CString(item1->GetDescription()).CmpNoCase(item2->GetDescription());
		 else if( item1->GetDescription() == NULL )
			 return 1;
		 else
			 return 0;
      case 3: //Ping asc 
         return item1->GetPing() - item2->GetPing(); 
      case 103: //Ping desc 
         return item2->GetPing() - item1->GetPing(); 
      case 4: //Users asc 
         return item1->GetUsers() - item2->GetUsers(); 
      case 104: //Users desc 
         return item2->GetUsers() - item1->GetUsers(); 
      case 5: //Files asc 
         return item1->GetFiles() - item2->GetFiles(); 
      case 105: //Files desc 
         return item2->GetFiles() - item1->GetFiles(); 
      case 6: //Preferences asc 
         return item2->GetPreferences() - item1->GetPreferences(); 
      case 106: //Preferences desc 
		  return item1->GetPreferences() - item2->GetPreferences(); 
      case 7: //failed asc 
         return item1->GetFailedCount() - item2->GetFailedCount(); 
      case 107: //failed desc 
		  return item2->GetFailedCount() - item1->GetFailedCount(); 
      case 8: //staticservers 
		  return item2->IsStaticMember() - item1->IsStaticMember(); 
      case 108: //staticservers-
		  return item1->IsStaticMember() - item2->IsStaticMember(); 
      default: 
         return 0; 
   } 
}

bool CServerListCtrl::StaticServerFileAppend(CServer *server)
{
	try
	{
		// Remove any entry before writing to avoid duplicates
		StaticServerFileRemove(server);

		FILE* staticservers = fopen(theApp.glob_prefs->GetAppDir() + wxString("staticservers.dat"), "a");
		if (staticservers==NULL) 
		{
			theApp.emuledlg->AddLogLine( false, GetResString(IDS_ERROR_SSF));
			return false;
		}
		
		if (fprintf(staticservers,
					"%s:%i,%i,%s\n",
					server->GetAddress(),
					server->GetPort(), 
					server->GetPreferences(),
					server->GetListName()) != EOF) 
		{
			theApp.emuledlg->AddLogLine(false, "'%s:%i,%s' %s", server->GetAddress(), server->GetPort(), server->GetListName(), GetResString(IDS_ADDED2SSF).GetData());
			server->SetIsStaticMember(true);
			theApp.emuledlg->serverwnd->serverlistctrl->RefreshServer(server);
		}

		fclose(staticservers);
	}
	catch (...)
	{
		return false;
	}
	return true;
}

bool CServerListCtrl::StaticServerFileRemove(CServer *server)
{
	try
	{
		if (!server->IsStaticMember())
			return true;

		wxString strLine;
		wxString strTest;
		char buffer[1024];
		int lenBuf = 1024;
		int pos;
		wxString StaticFilePath = theApp.glob_prefs->GetAppDir() + wxString("staticservers.dat");
		wxString StaticTempPath = theApp.glob_prefs->GetAppDir() + wxString("statictemp.dat");
		FILE* staticservers = fopen(StaticFilePath , "r");
		FILE* statictemp = fopen(StaticTempPath , "w");

		if ((staticservers == NULL) || (statictemp == NULL))
		{
			theApp.emuledlg->AddLogLine( false, GetResString(IDS_ERROR_SSF));
			return false;
		}

		while (!feof(staticservers))
		{
			if (fgets(buffer, lenBuf, staticservers) == 0)
				break;

			strLine = buffer;

			// ignore comments or invalid lines
			if (strLine.GetChar(0) == '#' || strLine.GetChar(0) == '/')
				continue;
			if (strLine.Length() < 5)
				continue;

			// Only interested in "host:port"
			pos = strLine.Find(",");
			if (pos == -1)
				continue;
			strLine = strLine.Left(pos);

			// Get host and port from given server
			strTest.Printf("%s:%i", server->GetAddress(), server->GetPort());

			// Compare, if not the same server write original line to temp file
			if (strLine.Cmp(strTest) != 0)
				fprintf(statictemp, buffer);
		}

		fclose(staticservers);
		fclose(statictemp);

		// All ok, remove the existing file and replace with the new one
		remove( StaticFilePath );
		rename( StaticTempPath, StaticFilePath );
	}
	catch (...)
	{
		return false;
	}
	return true;
}

void CServerListCtrl::ShowFilesCount() {
	wxString fmtstr = wxString::Format(_("Servers (%i)"), GetItemCount());
	wxStaticCast(FindWindowByName(wxT("serverListLabel")),wxStaticText)->SetLabel(fmtstr); 
}

